package com.wang.architecture.a_original;

import com.wang.architecture.a_original.dao.DemoDao;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @author wangchao05
 */
public class BeanFactory1 {

    /**
     * 这个beanMap 是缓存已经存在的bean 避免每次都要重新 生成一个bean
     */
    public static Map<String, Object> beanMap = new HashMap<>();

    private static Properties properties;
    static {
        properties = new Properties();
        try {
            properties.load(BeanFactory.class.getClassLoader().getResourceAsStream("factory.properties"));
        } catch (IOException e) {
            e.printStackTrace();
            // BeanFactory类的静态初始化都失败了，那后续也没有必要继续执行了
            throw new ExceptionInInitializerError("BeanFactory initialize error, cause: " + e.getMessage());
        }
    }


    public static Object getBean(String beanName) {
        try {
            Class<?> demoDao = Class.forName(properties.getProperty(beanName));
            return demoDao.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            throw new RuntimeException("BeanFactory have not [" + beanName + "] bean!", e);
        } catch (IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
            throw new RuntimeException("[" + beanName + "] instantiation error!", e);
        }
    }


    /**
     * 获取单例 bean  双重检测锁 防止线程不安全
     * @param beanName
     * @return
     */
    public static Object getBeanSingleton(String beanName) {
        if (!beanMap.containsKey(beanName)) {
            synchronized (BeanFactory1.class) {
                // 先锁住 BeanFactory1 类 然后判断 缓存的有没有
                if (!beanMap.containsKey(beanName)) {
                    // 过了双重检测，没有生成 bean，这里要生成bean
                    try {
                        Class<?> beanClazz  = Class.forName(properties.getProperty(beanName));
                        Object bean = beanClazz.newInstance();
                        // 将创建好的bean缓存起来
                        beanMap.put(beanName, bean);
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                        // 这个异常是没有找到对应的beanName的类
                        throw new RuntimeException("BeanFactory have not [" + beanName + "] bean!", e);
                    } catch (IllegalAccessException|InstantiationException e) {
                        e.printStackTrace();
                        // 这个异常时 实例化的 newInstance() 时候抛出来的，说明类存在但是初始化失败了
                        throw new RuntimeException("[" + beanName + "] instantiation error!", e);
                    }
                }
            }
        }
        return beanMap.get(beanName);
    }

}
